
package ifips.s7.vue;

import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import ifips.s7.modele.Automate;
import ifips.s7.modele.Turing;
import ifips.s7.modele.Etat;
import ifips.s7.modele.Etat_Turing;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class Console extends WindowAdapter implements WindowListener, ActionListener, Runnable
{
	private JFrame frame;
	private JTextArea textArea;
	private Thread reader;
	private Thread reader2;
	private boolean quit;
					
	private final PipedInputStream pin=new PipedInputStream(); 
	private final PipedInputStream pin2=new PipedInputStream(); 

	static String mot;
        Automate a;
        Turing tu;


        JButton Bclear;
        JToolBar tb;
        JButton tb_aut_open;
        JButton tb_tu_open;
        JButton tb_tu_det_open;
        private JFileChooser fc;
	public Console()
	{
		// create all components and add them
		frame=new JFrame("AutoCalComp");
		Dimension screenSize=Toolkit.getDefaultToolkit().getScreenSize();
		Dimension frameSize=new Dimension((int)(screenSize.width/2),(int)(screenSize.height/2));
		int x=(int)(frameSize.width/2);
		int y=(int)(frameSize.height/2);
		frame.setBounds(x,y,frameSize.width,frameSize.height);
		
		textArea=new JTextArea();
		textArea.setEditable(false);
		Bclear=new JButton("clear");
		tb = new JToolBar();
                tb_aut_open = new JButton("Open Automate");
                tb_tu_open = new JButton("Open Turing Machine");
                tb_tu_det_open = new JButton("Open Deterministic Turing Machine");
                tb.add(tb_aut_open);
                tb.add(tb_tu_open);
                tb.add(tb_tu_det_open);

		frame.getContentPane().setLayout(new BorderLayout());
		frame.getContentPane().add(new JScrollPane(textArea),BorderLayout.CENTER);
		frame.getContentPane().add(Bclear,BorderLayout.SOUTH);
                frame.getContentPane().add(tb,BorderLayout.NORTH);
		frame.setVisible(true);		
		
		frame.addWindowListener(this);		
		Bclear.addActionListener(this);
                tb_aut_open.addActionListener(this);
                tb_tu_open.addActionListener(this);
                tb_tu_det_open.addActionListener(this);
                
                try
		{
			PipedOutputStream pout=new PipedOutputStream(this.pin);
			System.setOut(new PrintStream(pout,true)); 
		} 
		catch (java.io.IOException io)
		{
			textArea.append("Couldn't redirect STDOUT to this console\n"+io.getMessage());
		}
		catch (SecurityException se)
		{
			textArea.append("Couldn't redirect STDOUT to this console\n"+se.getMessage());
	    } 
		
		try 
		{
			PipedOutputStream pout2=new PipedOutputStream(this.pin2);
			System.setErr(new PrintStream(pout2,true));
		} 
		catch (java.io.IOException io)
		{
			textArea.append("Couldn't redirect STDERR to this console\n"+io.getMessage());
		}
		catch (SecurityException se)
		{
			textArea.append("Couldn't redirect STDERR to this console\n"+se.getMessage());
	    } 		
			
		quit=false; // signals the Threads that they should exit
				
		// Starting two seperate threads to read from the PipedInputStreams				
		//
		reader=new Thread(this);
		reader.setDaemon(true);	
		reader.start();	
		//
		reader2=new Thread(this);	
		reader2.setDaemon(true);	
		reader2.start();
					
	}
	
	public synchronized void windowClosed(WindowEvent evt)
	{
		quit=true;
		this.notifyAll(); // stop all threads
		try { reader.join(1000);pin.close();   } catch (Exception e){}		
		try { reader2.join(1000);pin2.close(); } catch (Exception e){}
		System.exit(0);
	}		
		
	public synchronized void windowClosing(WindowEvent evt)
	{
		frame.setVisible(false); // default behaviour of JFrame	
		frame.dispose();
	}
	
	public synchronized void actionPerformed(ActionEvent evt)
	{
            if(evt.getSource().equals(Bclear))
		textArea.setText("");
            if(evt.getSource().equals(tb_aut_open)){
                fc = new JFileChooser(System.getProperty("user.dir"));
                fc.setApproveButtonText("Open Automate");
                textArea.setText("");
                if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION){
                        try {
                                a = parse_file(fc.getSelectedFile().getAbsolutePath());
                        } catch (FileNotFoundException ex) {
                            Logger.getLogger(Console.class.getName()).log(Level.SEVERE, null, ex);
                        } catch (IOException ex) {
                            Logger.getLogger(Console.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    System.out.println("Mot à lire : "+mot);
                    a.print();
                    System.out.println("Le mot est il lisible par l'automate? "+a.isReadable(mot));
                }
            }
            if(evt.getSource().equals(tb_tu_open)){
                fc = new JFileChooser(System.getProperty("user.dir"));
                fc.setApproveButtonText("Open Turing Machine");
                textArea.setText("");
                if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION){
                        try {
                                tu = turing_parse_file(fc.getSelectedFile().getAbsolutePath());
                        } catch (FileNotFoundException ex) {
                            Logger.getLogger(Console.class.getName()).log(Level.SEVERE, null, ex);
                        } catch (IOException ex) {
                            Logger.getLogger(Console.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    System.out.println("Mot à lire : "+mot);
                    tu.print();
                    System.out.println("Le mot est il lisible par la MTu? "+tu.isReadable(mot));
                }
            }
            if(evt.getSource().equals(tb_tu_det_open)){
                fc = new JFileChooser(System.getProperty("user.dir"));
                fc.setApproveButtonText("Open Det Turing Machine");
                textArea.setText("");
                if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION){
                        try {
                                tu = turing_parse_file(fc.getSelectedFile().getAbsolutePath());
                        } catch (FileNotFoundException ex) {
                            Logger.getLogger(Console.class.getName()).log(Level.SEVERE, null, ex);
                        } catch (IOException ex) {
                            Logger.getLogger(Console.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    System.out.println("Mot à lire : "+mot);
                    tu.print();
                    System.out.println("Quelle est le mot lu? "+tu.whatdoyouread(mot));
                }
            }
                

	}

	public synchronized void run()
	{
		try
		{			
			while (Thread.currentThread()==reader)
			{
				try { this.wait(100);}catch(InterruptedException ie) {}
				if (pin.available()!=0)
				{
					String input=this.readLine(pin);
					textArea.append(input);
				}
				if (quit) return;
			}
		
			while (Thread.currentThread()==reader2)
			{
				try { this.wait(100);}catch(InterruptedException ie) {}
				if (pin2.available()!=0)
				{
					String input=this.readLine(pin2);
					textArea.append(input);
				}
				if (quit) return;
			}			
		} catch (Exception e)
		{
			textArea.append("\nConsole reports an Internal error.");
			textArea.append("The error is: "+e);			
		}
		
		

	}
	
	public synchronized String readLine(PipedInputStream in) throws IOException
	{
                String input="";
                do
                {
                        int available=in.available();
                        if (available==0) break;
                        byte b[]=new byte[available];
                        in.read(b);
                        input=input+new String(b,0,b.length);
                }while( !input.endsWith("\n") &&  !input.endsWith("\r\n") && !quit);
                return input;
	}	
		
	public static void main(String[] arg) throws IOException
	{
                new Console();
       
	}

        public static Turing turing_parse_file(String f) throws FileNotFoundException, IOException{
                Turing tu = null;
                BufferedReader reader = new BufferedReader(new FileReader(f));

                String vide = reader.readLine();
                System.out.println("Element vide "+vide);
                tu = new Turing(vide);
                //Etats
                String etat;
                String e[];
                etat= reader.readLine();
                while(etat.length()!=0){
                    e = etat.split("\t");
                    tu.addEtat(new Etat_Turing(Integer.valueOf(e[0]),Boolean.valueOf(e[1]),Boolean.valueOf(e[2]) ));
                    etat= reader.readLine();
                }
                //Transition
                String transition;
                String t[];
                transition=reader.readLine();
                while(transition.length()!=0){
                    t = transition.split("\t");
                    boolean dir = true;
                    if(t[2].equals("G")) dir=false;
                    if(t.length < 5) tu.addTransition(tu.getEtat(Integer.valueOf(t[0])), t[1],dir, (String) null, tu.getEtat(Integer.valueOf(t[3])));
                    else tu.addTransition(tu.getEtat(Integer.valueOf(t[0])), t[1],dir, t[3] ,tu.getEtat(Integer.valueOf(t[4])));
                    transition=reader.readLine();
                }

                mot=reader.readLine();
                System.out.println("File Parsed");
                return tu;

    }


        public static Automate parse_file(String f) throws FileNotFoundException, IOException{
                Automate aut = null;
                BufferedReader reader = new BufferedReader(new FileReader(f));
                String vide = reader.readLine();
                System.out.println("Element vide "+vide);
                aut = new Automate(vide);
                //Etats
                String etat;
                String e[];
                etat= reader.readLine();
                while(etat.length()!=0){
                    e = etat.split("\t");
                    aut.addEtat(new Etat(Integer.valueOf(e[0]),Boolean.valueOf(e[1]),Boolean.valueOf(e[2]) ));
                    etat= reader.readLine();
                }
                //Transition
                String transition;
                String t[];
                transition=reader.readLine();
                while(transition.length()!=0){
                    t = transition.split("\t");
                    aut.addTransition(aut.getEtat(Integer.valueOf(t[0])), t[1], aut.getEtat(Integer.valueOf(t[2])));
                    transition=reader.readLine();
                }

                mot=reader.readLine();
                System.out.println("File Parsed");
                return aut;
    }
}